﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using Common;
using DataAccess;
using Common.Views;

namespace BusinessLogic
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "WCFUsers" in code, svc and config file together.
    public class WCFUsers : IWCFUsers
    {
        /// <summary>
        /// This method passes the user object in order for the account to be created
        /// </summary>
        /// <param name="newUser"></param>
        public void Register(User newUser)
        {
            new UsersRepository().Register(newUser);
        }

        /// <summary>
        /// This method checks whether the username exists and whether the password belongs to that username
        /// </summary>
        /// <param name="username"></param>
        /// <param name="password"></param>
        /// <returns>True if details match else false</returns>
        public bool IsAuthenticationValid(string username, string password)
        {
            return new UsersRepository().IsAuthenticationValid(username, password);
        }

        /// <summary>
        /// Gets a list of all countries
        /// </summary>
        /// <returns>A list of countries</returns>
        public IEnumerable<Country> GetCountries()
        {
            return new CountriesRepository().GetCountries();
        }

        /// <summary>
        ///  This method passes the details in the object to the repository method in order for the comment to be placed and linked to a product
        /// </summary>
        /// <param name="c"></param>
        public void PlaceComment(Comment c)
        {
            new CommentsRepository().PlaceComment(c);
        }

        /// <summary>
        /// This method passes the details in the object to the repository method in order for the rating to be placed and linked to a product
        /// </summary>
        /// <param name="r"></param>
        public void PlaceRating(Rating r)
        {
            new RatingsRepository().PlaceRating(r);
        }

        /// <summary>
        /// Gets the role's details according to the id passed
        /// </summary>
        /// <param name="roleId"></param>
        /// <returns>The role details</returns>
        public Role GetRole(int roleId)
        {
            return new UsersRepository().GetRole(roleId);
        }

        
        /// <summary>
        /// This method gets the user's order 
        /// </summary>
        /// <param name="username"></param>
        /// <returns>A list containg the order of the username passed</returns>
        public IEnumerable<Order> GetUserOrders(string username)
        {
            return new OrdersRepository().GetUserOrders(username);
        }

        /// <summary>
        /// This method adds a shopping cart object to store a user's shopping cart
        /// </summary>
        /// <param name="cart"></param>
        public void AddToCart(ShoppingCart cart)
        {
            new ShoppingCartRepository().AddToCart(cart);
        }

        /// <summary>
        /// This method removes all items and the object from the database
        /// </summary>
        /// <param name="scID"></param>
        public void DeleteCart(int scID)
        {
            new ShoppingCartRepository().DeleteCart(scID);
        }

        /// <summary>
        /// Gets the total amount of items in a user's shopping cart
        /// </summary>
        /// <param name="username"></param>
        /// <returns>An integer value. 0 if the user doesn't have an item in their cart</returns>
        public int GetNoOfItemsInShoppingCart(string username)
        {
            return new ShoppingCartRepository().GetNoOfItemsInShoppingCart(username);
        }

        /// <summary>
        /// Gets the product's id from the shopping cart
        /// </summary>
        /// <param name="productID"></param>
        /// <returns>All products id</returns>
        public int GetProductIDInShoppingCart(int productID)
        {
            return new ShoppingCartRepository().GetProductIDInShoppingCart(productID);
        }

        /// <summary>
        /// Gets the shopping cart object by its' id
        /// </summary>
        /// <param name="id"></param>
        /// <returns>The shopping cart object containg all details</returns>
        public ShoppingCart GetShoppingCartByID(int id)
        {
            return new ShoppingCartRepository().GetShoppingCartByID(id);
        }

        /// <summary>
        /// returns the contents of the shopping cart 
        /// </summary>
        /// <param name="username"></param>
        /// <returns>Item or item details found in the shopping cart</returns>
        public ShoppingCart ViewShoppingCart(string username)
        {
            return new ShoppingCartRepository().ViewShoppingCart(username);
        }

        /// <summary>
        /// Shows the contents of the shopping cart 
        /// </summary>
        /// <param name="username"></param>
        /// <returns>A list of items in the cart</returns>
        public IEnumerable<ShoppingCart> ListShoppingCart(string username)
        {
            return new ShoppingCartRepository().ListShoppingCart(username);
        }

        /// <summary>
        /// This method passes the order object in order for an order to be placed
        /// </summary>
        /// <param name="newOrder"></param>
        public void AddOrder(Order newOrder)
        {
            new OrdersRepository().AddOrder(newOrder);
        }

        /// <summary>
        /// This method passes the order details of that order to save the details of the order
        /// </summary>
        /// <param name="newOD"></param>
        public void AddOrderDetails(OrderDetail newOD)
        {
            new OrdersRepository().AddOrderDetails(newOD);

            Product thisP = new WCFProducts().GetProduct(newOD.Product_FK);
            thisP.Stock -= newOD.Quantity;
            new WCFProducts().UpdateProduct(thisP);
        }

        /// <summary>
        /// This menu displays the menu pages according to the user's role 
        /// </summary>
        /// <param name="roleId"></param>
        /// <returns>A list of pages</returns>
        public IEnumerable<Menu> GetMainMenus(int roleId)
        {
            return new MenusRepository().GetMainMenus(roleId);
        }

        /// <summary>
        /// This method gets a list of roles belonging to the username passed as a parameter
        /// </summary>
        /// <param name="username"></param>
        /// <returns>A list of roles</returns>
        public IQueryable<Role> GetUserRoles(string username)
        {
            return new RolesRepository().GetUserRoles(username);
        }

        /// <summary>
        /// This method gets a list of order details according to the order id passed as a parameter
        /// </summary>
        /// <param name="oID"></param>
        /// <returns>A list of order details</returns>
        public IQueryable<OrderDetail> GetOrderDetails(Guid oID)
        {
            return new OrdersRepository().GetOrderDetails(oID);
        }

        /// <summary>
        /// This menu gets the user's object details according to the username passed
        /// </summary>
        /// <param name="username"></param>
        /// <returns>User object containing the account information</returns>
        public User GetUser(string username)
        {
            return new UsersRepository().GetUser(username);
        }

        /// <summary>
        /// This method get's the order details id from the order id passed as a parameter 
        /// </summary>
        /// <param name="oID"></param>
        /// <returns>A list containing the order details</returns>
        public IQueryable<UserOrderDetailsView> GetOrderDetailsByOrderID(Guid oID)
        {
            return new OrdersRepository().GetOrderDetailsByOrderID(oID);
        }

        /// <summary>
        /// This method checks whether the email passed already belongs to another account
        /// </summary>
        /// <param name="email"></param>
        /// <returns>True if already in use else false</returns>
        public bool DoesEmailExist(string email)
        {
            return new UsersRepository().DoesEmailExist(email);
        }

        /// <summary>
        /// This method checks whether the username passed already belongs to another account
        /// </summary>
        /// <param name="username"></param>
        /// <returns>True if already in use else false</returns>
        public bool DoesUsernameExist(string username)
        {
            return new UsersRepository().DoesUsernameExist(username);
        }        

        /// <summary>
        /// This method gets the rating values for the user in order to rate a product
        /// </summary>
        /// <returns>A list of rating options (1,2,3,4,5)</returns>
        public IEnumerable<RatingOption> GetRatingsOptions()
        {
            return new RatingsRepository().GetRatingsOptions();
        }

        /// <summary>
        /// This method allows a user to view their shoppingcart
        /// </summary>
        /// <param name="username"></param>
        /// <returns>A list of the shopping cart</returns>
        public IEnumerable<ShoppingCartView> DisplayShoppingCart(string username)
        {
            return new ShoppingCartRepository().DisplayShoppingCart(username);
        }

        /// <summary>
        /// Passes the userfault object in order to save the user's reported fault
        /// </summary>
        /// <param name="uf"></param>
        public void SubmitFault(UserFault uf)
        {
            new FaultsRepository().SubmitFault(uf);
        }

        /// <summary>
        /// Gets all the faults for the user with the username passed
        /// </summary>
        /// <param name="username"></param>
        /// <returns>A list of the user's reported fault</returns>
        public IEnumerable<FaultDetailsView> GetFaultDetailsForUser(string username)
        {
            return new FaultsRepository().GetFaultDetailsForUser(username);
        }

        /// <summary>
        /// Gets all faults which were not reported by the admin
        /// </summary>
        /// <param name="username"></param>
        /// <returns>A list of faults</returns>
        public IEnumerable<FaultDetailsView> GetFaultDetailsForAdmin(string username)
        {
            return new FaultsRepository().GetFaultDetailsForAdmin(username);
        }

        /// <summary>
        /// Filters the faults by the date and the product
        /// </summary>
        /// <param name="username"></param>
        /// <param name="fromDate"></param>
        /// <param name="toDate"></param>
        /// <param name="productID"></param>
        /// <returns>A list of faults for that product between the specified dates</returns>
        public IEnumerable<FaultDetailsView> GetFilteredFaultDetailsForUser(string username, string fromDate, string toDate, int productID)
        {
            return new FaultsRepository().GetFilteredFaultDetailsForUser(username, fromDate, toDate, productID);
        }

        /// <summary>
        /// Gets the fault details by the username and the ticket number to be displayed in the pdf
        /// </summary>
        /// <param name="username"></param>
        /// <param name="ticketNo"></param>
        /// <returns>A list of faults</returns>
        public IEnumerable<FaultDetailsView> GetFaultDetailsForPDF(string username, int ticketNo)
        {
            return new FaultsRepository().GetFaultDetailsForPDF(username, ticketNo);
        }

        /// <summary>
        /// Gets the order details according to the order id and the product id passed as parameters
        /// </summary>
        /// <param name="oID"></param>
        /// <param name="pID"></param>
        /// <returns>A list of order details</returns>
        public IQueryable<UserOrderDetailsView> GetOrderDetailsByOrderIDandProductID(Guid oID, int pID)
        {
            return new OrdersRepository().GetOrderDetailsByOrderIDandProductID(oID, pID);
        }

        /// <summary>
        /// This method gets a userfault object by the id passed 
        /// </summary>
        /// <param name="id"></param>
        /// <returns>A userfault object</returns>
        public UserFault GetFaultByID(int id)
        {
            return new FaultsRepository().GetFaultByID(id);
        }

        /// <summary>
        /// This method adds a new row to show that the fault has been updated
        /// </summary>
        /// <param name="newUF"></param>
        public void UpdateFault(UserFault newUF)
        {
            new FaultsRepository().UpdateFault(newUF);
        }

        /// <summary>
        /// This method gets a list of usernames to be used in the faults filter for the administrator
        /// </summary>
        /// <returns>A list of usernames</returns>
        public IEnumerable<User> GetUsernames()
        {
            return new UsersRepository().GetUsernames();
        }

        /// <summary>
        /// This method gets the fault according to the token number and the username passed
        /// </summary>
        /// <param name="tn"></param>
        /// <param name="username"></param>
        /// <returns>A list containg the userfaults</returns>
        public IEnumerable<FaultDetailsView> GetFaultByTokenNumber(int tn, string username)
        {
            return new FaultsRepository().GetFaultByTokenNumber(tn, username);
        }

        /// <summary>
        /// This method orders faults by the date in descending order
        /// </summary>
        /// <returns>A list of all faults in descending order</returns>
        public IEnumerable<FaultDetailsView> FilterFaultsByDate()
        {
            return new FaultsRepository().FilterFaultsByDate();
        }

        /// <summary>
        /// This method orders faults by the faults date in descending order
        /// </summary>
        /// <param name="admin"></param>
        /// <returns>All faults which do not belong to the loged in admin</returns>
        public IEnumerable<FaultDetailsView> FilterFaultsByDateForAdmin(string admin)
        {
            return new FaultsRepository().FilterFaultsByDateForAdmin(admin);
        }

        /// <summary>
        /// This method is used by administrators to filter faults by the username and token number and by date if entered
        /// </summary>
        /// <param name="username"></param>
        /// <param name="tokenNumber"></param>
        /// <param name="fromD"></param>
        /// <param name="toDate"></param>
        /// <returns></returns>
        public IEnumerable<FaultDetailsView> AdvancedFaultSearch(string username, int tokenNumber, string fromD, string toDate)
        {
            return new FaultsRepository().AdvancedFaultSearch(username, tokenNumber, fromD, toDate);
        }

        /// <summary>
        /// This method shows the user the faults for the product chosen
        /// </summary>
        /// <param name="pID"></param>
        /// <param name="username"></param>
        /// <returns>A list of faults</returns>
        public IEnumerable<FaultDetailsView> GetAllFaultsForThisProduct(int pID, string username) 
        {
            return new FaultsRepository().GetAllFaultsForThisProduct(pID, username);
        }

        /// <summary>
        /// Gets the top 10 highest rated products
        /// </summary>
        /// <returns>A list of the highest rated products</returns>
        public IEnumerable<StatisticalReportView> GetTopRatedProducts()
        {
            return new StatisticsRepository().GetTopRatedProducts();
        }

        /// <summary>
        /// Gets the top 10 most purchased products
        /// </summary>
        /// <returns>A list of the most purchased products</returns>
        public IEnumerable<StatisticalReportView> GetMostPurchasedProduct()
        {
            return new StatisticsRepository().GetMostPurchasedProduct();
        }

        /// <summary>
        /// Gets the top 10 products with the most faults
        /// </summary>
        /// <returns>A list of the top 10 products with the most faults</returns>
        public IEnumerable<StatisticalReportView> GetProductWithHighestNumberOfFaults()
        {
            return new StatisticsRepository().GetProductWithHighestNumberOfFaults();
        }

        /// <summary>
        /// Gets the top 10 products with the least faults
        /// </summary>
        /// <returns>A list of the top 10 products with the least faults</returns>
        public IEnumerable<StatisticalReportView> GetProductWithLeastNumberOfFaults()
        {
            return new StatisticsRepository().GetProductWithLeastNumberOfFaults();
        }

        /// <summary>
        /// Gets the order details from the fault number passed as a parameter
        /// </summary>
        /// <param name="tn"></param>
        /// <returns>A list of the order details which contain the token number</returns>
        public IEnumerable<UserOrderDetailsView> GetOrderDetailsFromFaultNO(int tn)
        {
            return new OrdersRepository().GetOrderDetailsFromFaultNO(tn);
        }

        /// <summary>
        /// Gets the userfault object details for the first reported fault by the token number
        /// </summary>
        /// <param name="tn"></param>
        /// <returns>The object so as to get the date of when the fault was first reported</returns>
        public UserFault GetFaultsFirstDateByTokenNumber(int tn)
        {
            return new FaultsRepository().GetFaultsFirstDateByTokenNumber(tn);
        }
    }
}
